<!------------------------------------------------------->
<!--  WEB CALCULATOR USING PHP AND REGULAR EXPRESSIONS -->
<!--  Author: Atindriyo Sanyal -->
<!-- UID : 303-986-288 -->
<!------------------------------------------------------->

<!------------------------------------------------->
<!--     HTML code for the front end design      -->
<!------------------------------------------------->

<html>
<head>

<!------------------------------------------------->
<!--   CSS Code for Textbox and Button Design    -->
<!------------------------------------------------->

<style type="text/css">
@CHARSET "UTF-8";

.search-query {
    border-radius: 14px 14px 14px 14px;
    margin-bottom: 0;
    padding-left: 14px;
    padding-right: 14px;
}

button.btn, input.btn[type="submit"] {
}

button.btn, input.btn[type="submit"] {
}

input[type="button"], input[type="reset"], input[type="submit"] {
    height: auto;
    width: auto;
}

button, input[type="button"], input[type="reset"], input[type="submit"] {
    cursor: pointer;
}

input[type="button"], input[type="reset"], input[type="submit"] {
    height: auto;
    width: auto;
}

button, input[type="button"], input[type="reset"], input[type="submit"] {
    cursor: pointer;
}

.btn-danger {
    background-color: #DA4F49;
    background-image: -moz-linear-gradient(center top , #EE5F5B, #BD362F);
    background-repeat: repeat-x;
    border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
}

.btn {
    -moz-border-bottom-colors: none;
    -moz-border-image: none;
    -moz-border-left-colors: none;
    -moz-border-right-colors: none;
    -moz-border-top-colors: none;
    background-color: #F5F5F5;
    background-image: -moz-linear-gradient(center top , #FFFFFF, #E6E6E6);
    background-repeat: repeat-x;
    border-color: #CCCCCC #CCCCCC #B3B3B3;
    border-radius: 4px 4px 4px 4px;
    border-style: solid;
    border-width: 1px;
    box-shadow: 0 1px 0 rgba(255, 255, 255, 0.2) inset, 0 1px 2px rgba(0, 0, 0, 0.05);
    color: #333333;
    cursor: pointer;
    display: inline-block;
    font-size: 13px;
    line-height: 18px;
    margin-bottom: 0;
    padding: 4px 10px;
    text-align: center;
    text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);
    vertical-align: middle;
}

.btn-danger {
    background-color: #DA4F49;
    background-image: -moz-linear-gradient(center top , #EE5F5B, #BD362F);
    background-repeat: repeat-x;
    border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
}

</style>

</head>

<div id="wrapper"
	style="margin-top: 20px; margin-left: 20px;">
<h2>Calculator</h2>
<i>By Atindriyo Sanyal (UID: 303986288)</i> <br />
<br />
<ul>
	<li>Numbers and operators like +,-,* and / and also parenthesis are
	allowed in the expression.</li>
	<li>The evaluation follows the standard operator precedence.</li>
	<li>The calculator ignores parentheses.</li>
	<li>Expressions like 3--22 will work only if spacing is given properly
	(e.g. 3- -22)</li>
	<li>Error messages for Invalid Expression, Divide by Zero Error, 0/0
	Error, Contiguous Dots etc.</li>
	<li>Takes care of spaces between tokens</li>
	<li>Technologies used:
	<ul>
		<li>HTML</li>
		<li>CSS</li>
		<li>PHP</li>
	</ul>
	</li>
</ul>

<br />


<form method="post">
<span>Type an expression in the following box:</span><br />
<br />
<input class="input-medium search-query"
	style="height: 30px; width: 250px;" type="text" name="display"
	value='<?php 
	   				if($_REQUEST['submit']){
						echo $_REQUEST['display'];
					}
	   		  ?>' /> 
<input class="btn btn-danger" type="submit" name="submit"
	value="Calculate" /></form>
<hr />

<!------------------------------------>
<!--  END OF HTML CODE --> 
<!------------------------------------>

<?php
error_reporting(0);                       			//Turn off Errors

if($_REQUEST['submit']){
	echo "<h2>Result</h2>";

	//  Displays the Expression and the Result
	echo "<div style=\"height:30px; background:#FFA366;\"><b>Expression</b>: ".$_REQUEST['display']."</div>";
	
	echo "<div style=\"height:30px; background:#B2B2E0;\"><b>Answer</b>: ". evaluate($_REQUEST['display'])."</div>";
}

/**
 * 
 * ---------------------------------------------------------------------------------
 * @desc Function to check if there's any 0/0 operation in our given expression
 * @author Atindriyo Sanyal
 * @param string $expression
 * ---------------------------------------------------------------------------------
 * 
 */

function checkZeroByZero($expression){

	$invalid_pattern = "/([^0-9]0\/0)|(0\/0)/";
	
	preg_match_all($invalid_pattern, $expression, $matches);
	
	unset($matches[0]);
	
	return (sizeof($matches[1])>0)?true : false;

}

/**
 * 
 * ---------------------------------------------------------------------------------
 * @desc Function to check the presence of the following:
 * 		 - invalid characters (characters apart from numerals, decimals and operators)
 * 		 - presence of contiguous decimals in an operand
 * 		 - presence of invalid operands
 * 
 * @author Atindriyo Sanyal
 * @param string $expression
 * ---------------------------------------------------------------------------------
 * 
 */

function checkInvalidExpression($expression){
	
	$invalid_pattern = "/([^0-9\+\-\*\/\.\s\(\)])/";
	$invalid_operand_pattern = "/(\)[0-9]+)/";
	$contiguous_dots = "/(\.\.+)/";
	
	preg_match_all($invalid_pattern, $expression, $matches);
	unset($matches[0]);
	
	preg_match_all($invalid_operand_pattern, $expression, $matches2);
	unset($matches2[0]);
	
	preg_match_all($contiguous_dots, $expression, $matches3);
	unset($matches3[0]);
	
	return (sizeof($matches[1])>0||sizeof($matches2[1])>0||sizeof($matches3[1])>0) ? true : false;
}

/**
 * 
 * ---------------------------------------------------------------------------------
 * @desc Function to check if there's any 0/0 operation in our given expression
 * @author Atindriyo Sanyal
 * @param string $expression
 * ---------------------------------------------------------------------------------
 * 
 */

function checkContinuousOperators($expression){
	
	$continuous_operator_pattern = "/(\+\*)|(\/\*)|(\*\/)|(\-\*)|(\+\/)|(\-\/)|(\*\*)|(\/\/)/";
	preg_match_all($continuous_operator_pattern, $expression, $matches);
	
	unset($matches[0]);
	return sizeof($matches[1]);
	
}

/**
 * 
 * ---------------------------------------------------------------------------------
 * @desc Function to check if there's a Divide by zero operation in our given expression
 * @author Atindriyo Sanyal
 * @param string $expression
 * ---------------------------------------------------------------------------------
 * 
 */

function checkDivideByZero($expression){
	
	$divide_by_zero_pattern = "/([0-9]+?\/0)/";
	
	preg_match_all($divide_by_zero_pattern, $expression, $divideZeroMatches);
		
	unset($divideZeroMatches[0]);
	
	return ((sizeof($divideZeroMatches[1]) > 0) &&
					 	  ($expression!="0/0"))? true : false;
}

/**
 * 
 * ---------------------------------------------------------------------------------
 * @desc The main function to evaluate the expression
 * @author Atindriyo Sanyal
 * @param string $expression
 * ---------------------------------------------------------------------------------
 * 
 */

function evaluate($expression){

	
	if(checkInvalidExpression($expression)||checkContinuousOperators($expression)){
		$error_string = "Invalid Expression. ";
	}
	
	else if(checkDivideByZero($expression)){
		$error_string.= "Divide by Zero Error.";
	}
	
	else if(checkZeroByZero($expression)){
		$error_string.= "0/0 is Mathematically Invalid.";
	}

	
	else{
	
		eval('$x='.preg_replace('/[^0-9\+\-\*\/\s\.]/', '', $expression).';');
		
		if($x!="")
		return $x;
		
		else $error_string = "Invalid Expression";
		
		
	}
	
	return $error_string;
}

?></div>
</html>